#pragma once

#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <strings.h>
#include <functional>

#include "log.hpp"
#include "inetaddr.hpp"
using namespace mylog;
using namespace myaddr;
// using func_t = std::function<std::string(const std::string &)>;
using server_func_t = std::function<void(int sockfd, const std::string &, const InetAddr &)>;
namespace udpserver
{
    const static int default_fd = -1;
    class UdpServer
    {
    public:
        UdpServer(uint16_t port, server_func_t func)
            : _sockfd(default_fd), _port(port), _running(false), _func(func)
        {
        }
        ~UdpServer()
        {
        }
        void Init()
        {
            // 打开网络文件
            _sockfd = socket(AF_INET, SOCK_DGRAM, 0);
            if (_sockfd < 0)
            {
                LOG(Level::FATAL) << "socket error";
                exit(1);
            }
            LOG(Level::INFO) << "socket success, _sockfd : " << _sockfd;
            // 绑定端口号
            struct sockaddr_in skd;
            bzero(&skd, sizeof(skd));    // 置0
            skd.sin_family = AF_INET;    // 网络通信
            skd.sin_port = htons(_port); // htons 本地转网络(字符序列)
            // inet_addr()  字符ip  -->  4字节ip  --> 网络序列
            skd.sin_addr.s_addr = INADDR_ANY;

            int n = bind(_sockfd, (struct sockaddr *)&skd, sizeof(skd));
            if (n < 0)
            {
                LOG(Level::FATAL) << "bind error";
                exit(2);
            }
            LOG(Level::INFO) << "bind success, _sockfd : " << _sockfd;
        }
        void Start()
        {
            _running = true;
            // 接受信息
            while (_running)
            {
                char buff[256];
                struct sockaddr_in peer;
                socklen_t len = sizeof(peer);
                // 接受信息
                ssize_t n = recvfrom(_sockfd, buff, sizeof(buff) - 1, 0, (struct sockaddr *)&peer, &len);
                buff[n] = '\0';

                _func(_sockfd, buff, InetAddr(peer));
            }
        }

    private:
        int _sockfd;
        uint16_t _port; // 端口号
        bool _running;
        server_func_t _func;
    };
}
